package cn.stylefeng.guns.workflow.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.guns.base.exception.BusinessException;
import cn.stylefeng.guns.base.pojo.page.LayuiPageFactory;
import cn.stylefeng.guns.workflow.modeler.ProcessDefinition;
import cn.stylefeng.guns.workflow.service.ProcessDefinitionService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
* @author: lujie
* @create: 2020/10/29
* @description: 流程定义Service
**/
@Service
public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {

    @Autowired
    private RuntimeService runtimeService;

    /**
     * 流程资源管理类
     */
    @Autowired
    private RepositoryService repositoryService;

    @Override
    public Page<ProcessDefinition> pageList(ProcessDefinition processDefinition) {
        Page page = LayuiPageFactory.defaultPage();
        Long pageNum = page.getCurrent();
        Long pageSize = page.getSize();
        ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
        if (StrUtil.isNotBlank(processDefinition.getName())){
            definitionQuery.processDefinitionNameLike("%"+processDefinition.getName()+"%");
        }
        if (StrUtil.isNotBlank(processDefinition.getKey())){
            definitionQuery.processDefinitionKeyLike("%"+ processDefinition.getKey()+"%");
        }
        if (StrUtil.isNotBlank(processDefinition.getCategory())){
            definitionQuery.processDefinitionCategoryLike("%"+processDefinition.getCategory()+"%");
        }
        List<org.activiti.engine.repository.ProcessDefinition> processDefinitionList;
        if (pageNum != null && pageSize != null) {
            long totalCount = definitionQuery.count();
            processDefinitionList = definitionQuery.listPage(Long.valueOf((pageNum - 1L) * pageSize).intValue(), pageSize.intValue());
            page.setCurrent(pageNum);
            page.setSize(pageSize);
            page.setTotal(totalCount);
        } else {
            processDefinitionList = definitionQuery.list();
        }
        List<ProcessDefinition> result = new ArrayList<>();
        processDefinitionList.forEach(definition->{
            ProcessDefinitionEntityImpl entityImpl = (ProcessDefinitionEntityImpl) definition;
            cn.stylefeng.guns.workflow.modeler.ProcessDefinition entity = new cn.stylefeng.guns.workflow.modeler.ProcessDefinition();
            BeanUtil.copyProperties(entityImpl, entity);
            Deployment deployment = repositoryService.createDeploymentQuery()
                    .deploymentId(definition.getDeploymentId())
                    .singleResult();
            entity.setDeploymentTime(deployment.getDeploymentTime());
            entity.setDiagramResourceName(definition.getDiagramResourceName());
            entity.setResourceName(definition.getResourceName());
            entity.setSuspendState(entityImpl.getSuspensionState() + "");
            entity.setSuspendStateName(entityImpl.getSuspensionState() == 1 ? "已激活":"未激活");
            result.add(entity);
        });

        page.setRecords(result);
        return page;
    }



    @Override
    public void suspendOrActiveApply(String id, String suspendState) {
        if ("1".equals(suspendState)) {
            // 当流程定义被挂起时，已经发起的该流程定义的流程实例不受影响（如果选择级联挂起则流程实例也会被挂起）。
            // 当流程定义被挂起时，无法发起新的该流程定义的流程实例。
            // 直观变化：act_re_procdef 的 SUSPENSION_STATE_ 为 2
            repositoryService.suspendProcessDefinitionById(id);
        } else if ("2".equals(suspendState)) {
            repositoryService.activateProcessDefinitionById(id);
        }

    }

    @Override
    public int deleteProcessDeploymentByIds(String ids) {
        String[] deploymentIdsArr = Convert.toStrArray(ids);
        int counter = 0;
        for (String deploymentId: deploymentIdsArr) {
            List<ProcessInstance> instanceList = runtimeService.createProcessInstanceQuery()
                    .deploymentId(deploymentId)
                    .list();
            if (!CollectionUtils.isEmpty(instanceList)) {
                // 存在流程实例的流程定义
                throw BusinessException.ERROR("已存在运行中的流程，不可删除");
            }
            // true 表示级联删除引用，比如 act_ru_execution 数据
            repositoryService.deleteDeployment(deploymentId, true);
            counter++;
        }
        return counter;
    }
}
